/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.google.code.jbrnes.core;

import java.util.Stack;

/**
 *
 * @author Leandro
 */
public class Cpu {
    public static final int NUMBER_INSTRUCTIONS = 18;
    
    public static int regAccumulator; 
    public static int regIndexX;
    public static int regIndexY;    
    public static int regStatus;
        public static boolean fCarry;
        public static boolean fZero;
        public static boolean fInterrupt;
        public static boolean fDecimal = false;
        public static boolean fBreak;
        public static boolean fUnused = true;
        public static boolean fOverflow;
        public static boolean fNegativeSign;
    public static int regProgramCounter;
    public static int regStackPointer;
    public static Stack<Integer> realStack;    
        
    public static CpuMemory memory = new CpuMemory();        
    public static int[] cicles = new int[NUMBER_INSTRUCTIONS];
    
    public static void init()
    {       
        //fill cicles [opcode] number of cicles
        cicles[0x0000] = 7;
        cicles[0x008A] = 2;        
        cicles[0x0098] = 2;
        cicles[0x009A] = 2;
        cicles[0x00A8] = 2; 
        cicles[0x00AA] = 2; 
        cicles[0x00BA] = 2; 
        
    }
    
    protected Cpu(){
    }
    
    public static void execute() throws Exception{
        regProgramCounter = memory.readFrom(0xffff);
        memory.writeAt(0x11a0, 0x140f);
        
        int opCode = memory.readFrom(regProgramCounter++);        
        int quantityCicles = cicles[opCode];
        
        switch (opCode){
            case CpuCode.BRK:
                BRK();
            default:
                throw new Exception("Illegal opcode[" + regProgramCounter + "]");
        }
    
        
        
    }
    
    private static void setBreak(boolean vl){
        fBreak = vl ;
    }
    private static void setCarry(boolean vl){
        fCarry  = vl ;
    }
    private static void setZero(boolean vl){
        fZero = vl ;
    }
    private static void setInterrupt(boolean vl){
        fInterrupt = vl ;
    }
    private static void setOverflown(boolean vl){
        fOverflow = vl ;
    }
    private static void setNegativeSign(boolean vl){
        fNegativeSign = vl ;
    }
    public static int getRegStatus(){
        assemblyRegStatus();
        return regStatus;
    }
    
    private static String assStatus;    
    private static final String one = "1";
    private static final String zero = "0";
    private static void assemblyRegStatus(){
    // Bit No.  7   6   5   4   3   2   1   0
    //          S   V       B   D   I   Z   C
        
      //  (fNegativeSign) ? assStatus = one : assStatus = zero ;
        
        regStatus = Integer.parseInt("0001", 2);
    }
     

    private static void BRK(){        
        setBreak(true);
        regStackPointer = regProgramCounter + 1;
        regStackPointer = getRegStatus();
        setInterrupt(true);
        regProgramCounter = memory.readFrom(0xfffe);
        }
    
    private static void TAY(){
        regIndexY = regAccumulator;
    }
    private static void TAX(){
        regIndexX = regAccumulator;
    }
    private static void TSX(){
        regIndexX = regStackPointer;
    }
    private static void TYA(){
        regAccumulator = regIndexY;
    }
   private static void TXA(){
        regAccumulator = regIndexX;
    }
    private static void TXS(){
        regStackPointer = regIndexX ;
    }
  
    
    
    /**
     * Method to make endianess function.<br>
     * adress ffff data 00000001<br>
     * adress fffe data 00000001<br><br>
     *            
     *           0000000100000000<br> 
     *           0000000000000001<br>
     *           ----------------<br>
     *           0000000100000001 = 16bit using the <b>low-endian</b> scheme<br> 
     * 
     * @param highAdress the most high adress that wishes merge.
     * @param lowAdress the most low adress that wishes merge.
     * @return data from cpu memory
     */
    public static int readBigWord(int highAdress,int lowAdress){        
        return (memory.readFrom(lowAdress) | (memory.readFrom(highAdress) <<8));
        //  adress ffff data 10110100
        //  adress fffe data 11011010
        //         
        //        1011010000000000 
        //        0000000011011010
        //        ----------------
        //        1011010011011010 =16bit using the low-endian scheme
    }
    
}
